package com.toulezu.test.redis.serializer;

import com.toulezu.test.utils.GZIPUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

/**
 * 序列化/反序列化实现类
 * 将对象转成字节数组后，通过 gzip 对字节数组压缩
 * 将字节数组转成对象前，通过 gzip 对字节数组解压
 */
public class GzipObjectSerializer implements RedisSerializer<Object>  {

    private Converter<Object, byte[]> serializer = new SerializingConverter();
    private Converter<byte[], Object> deserializer = new DeserializingConverter();

    static final byte[] EMPTY_ARRAY = new byte[0];

    /**
     * 将 gzip 字节数组转成对象
     *
     * 1. 首先将 gzip 字节数组转成普通字节数组
     * 2. 再将普通字节数组转成对象
     *
     * @param bytes
     * @return
     */
    public Object deserialize(byte[] bytes) {
        if (isEmpty(bytes)) {
            return null;
        }

        try {
            return deserializer.convert(GZIPUtils.uncompress(bytes));
        } catch (Exception ex) {
            throw new SerializationException("Cannot deserialize", ex);
        }
    }

    /**
     * 将对象序列化成 gzip 字节数组
     *
     * 1. 首先将对象序列化成普通字节数组
     * 2. 再将普通字节数组转成 gzip 字节数组
     *
     * @param object
     * @return byte[] gzip bytes
     */
    public byte[] serialize(Object object) {
        if (object == null) {
            return EMPTY_ARRAY;
        }
        try {
            byte[] bytes = serializer.convert(object);
            return GZIPUtils.compress(bytes);
        } catch (Exception ex) {
            return EMPTY_ARRAY;
        }
    }

    private boolean isEmpty(byte[] data) {
        return (data == null || data.length == 0);
    }

}
